import 'dart:math';

import 'package:flutter/material.dart';

class PaintModel extends StatefulWidget {
  @override
  _PaintModelState createState() => _PaintModelState();
}

class _PaintModelState extends State<PaintModel>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  List<Snowflake> _sonwflakes = List.generate(100, (index) => Snowflake());

  @override
  void initState() {
    // TODO: implement initState
    _controller = AnimationController(
      duration: Duration(seconds: 10),
      vsync: this,
    )..repeat();
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('paint module page')),
      body: Container(
        width: double.infinity,
        height: double.infinity,
        color: Colors.blue,
        child: AnimatedBuilder(
          animation: _controller,
          builder: (_, Widget widget) {
            _sonwflakes.forEach((sonwflake) => sonwflake.fall());
            return CustomPaint(
              painter: PainterClass(_sonwflakes),
            );
          },
        ),
      ),
    );
  }
}

class PainterClass extends CustomPainter {
  final List<Snowflake> _sonwflakes;
  final Paint whitePaint = Paint()..color = Colors.white;

  PainterClass(this._sonwflakes);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawCircle(size.center(Offset(0, 100)), 20.0, whitePaint);
    canvas.drawOval(
      Rect.fromCenter(
        center: size.center(Offset(0, 240)),
        width: 200,
        height: 250,
      ),
      whitePaint,
    );

    _sonwflakes.forEach((sonwflake) {
      canvas.drawCircle(
        Offset(sonwflake.x, sonwflake.y),
        sonwflake.radius,
        whitePaint,
      );
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

class Snowflake {
  double x = Random().nextDouble() * 400;
  double y = Random().nextDouble() * 800;
  double radius = Random().nextDouble() * 2 + 2;
  double velocity = Random().nextDouble() * 1 + 2;

  fall() {
    y += velocity;
    if (y > 800) {
      y = 0;
      x = Random().nextDouble() * 400;
      radius = Random().nextDouble() * 2 + 2;
      velocity = Random().nextDouble() * 4 + 2;
    }
  }
}
